package zap

import (
	"encoding/json"
	"fmt"

	"go.uber.org/zap"
	"go.uber.org/zap/zapcore"
)

var (
	c      ZapConfig   // zap配置
	LOGGER *zap.Logger // 记录器，使用时，直接引入此包，然后"LOGGER.Debug(msg, fields...)"
	level  zapcore.Level
)

type ZapConfig struct {
	Level         string `mapstructure:"level" json:"level" yaml:"level"`                           // 级别
	Format        string `mapstructure:"format" json:"format" yaml:"format"`                        // 输出模式，json/console
	LogInConsole  bool   `mapstructure:"log-in-console" json:"logInConsole" yaml:"log-in-console"`  // 输出控制台
	Prefix        string `mapstructure:"prefix" json:"prefix" yaml:"prefix"`                        // 日志前缀
	TimeFormat    string `mapstructure:"time-format" json:"timeFormat" yaml:"time-format"`          // 时间格式
	ShowLine      bool   `mapstructure:"show-line" json:"showLine" yaml:"show-line"`                // 显示代码行号
	EncodeLevel   string `mapstructure:"encode-level" json:"encodeLevel" yaml:"encode-level"`       // 编码级
	StacktraceKey string `mapstructure:"stacktrace-key" json:"stacktraceKey" yaml:"stacktrace-key"` // 栈名

	// 文件
	Directory      string            `mapstructure:"directory" json:"directory"  yaml:"directory"`                    // 日志文件夹
	FileNamePrefix string            `mapstructure:"file-name-prefix" json:"fileNamePrefix"  yaml:"file-name-prefix"` // 日志文件前缀
	ZapCompress    ZapCompressConfig `mapstructure:"zap-compress" json:"zapCompress"  yaml:"zap-compress"`            // 日志文件压缩归档
}

func (z ZapConfig) Load() {
	c = z
	if LOGGER != nil { //是否开启模块
		return
	}
	j, _ := json.Marshal(z)
	fmt.Printf("开启zap模块：%s\n", string(j))
	z.level()
	writer := z.fileWriteSyncer(z.logFile())
	encoder := z.getEncoder()
	core := zapcore.NewCore(encoder, writer, levelEnablerFunc)
	LOGGER = zap.New(core)
	if z.ShowLine {
		LOGGER = LOGGER.WithOptions(zap.AddCaller())
	}
}

// 日志记录判断
var levelEnablerFunc zap.LevelEnablerFunc = func(l zapcore.Level) bool {
	return l >= level
}

// 日志等级
func (z ZapConfig) level() {
	l, err := zap.ParseAtomicLevel(z.Level)
	if err != nil {
		panic(err)
	}
	level = l.Level()
}
